/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package simulateurs.model.automate;
import java.util.ArrayList;
import simulateurs.model.monde.Point;
import simulateurs.model.monde.StringPoint;
import simulateurs.model.monde.StringPointIndiceligneconditions;
/**
 *
 * @author Jah
 */
public class Automate {
    
    protected ArrayList<String> listeEtats;
    protected ArrayList<ArrayList<EtatsuivCondsAction>> listePtrEtats;
    protected int indiceEtatCourant;
    
    // constructeurs
    // IL FAUT PENSER A CLONER LA LISTE LORS DE l'appel du constructeur
    
    // constructeur par defaut pour le parser
    public Automate(){
        setListeEtats(new ArrayList<String>());
        setListePtrEtats(new ArrayList<ArrayList<EtatsuivCondsAction>>());
        setIndiceEtatCourant(0);
}
    
    public Automate(ArrayList<String> listeEtats,ArrayList<ArrayList<EtatsuivCondsAction>> listePtrEtats,int indiceEtatCourant){
        setListeEtats(listeEtats);
        setListePtrEtats(listePtrEtats);
        setIndiceEtatCourant(indiceEtatCourant);
    }
    
    public Automate(ArrayList<String> listeEtats,ArrayList<ArrayList<EtatsuivCondsAction>> listePtrEtats){
        setListeEtats(listeEtats);
        setListePtrEtats(listePtrEtats);
        setIndiceEtatCourant(0);
    }
    
    //  public int rechercherEvent(Evenement event)
    
    //public Action update(Evenement event) // a revoir !!!
    // ne doit pas renvoyer des evenements mais des ACTIONS !!!
    public StringPoint update(ArrayList<StringPoint> listeEvents){
        int etatSuivant;
        //Point point = null;
        StringPoint actionPoint = null;
        StringPointIndiceligneconditions actionPointIndex = null;
        StringPoint eventPoint = null;
        ArrayList<StringPointIndiceligneconditions> actionPointIndexList = null;
        ArrayList<EtatsuivCondsAction> lignesTable;
        //System.out.println("l'indice de l'etat suivant est : " + getIndiceEtatCourant());
        
        lignesTable = listePtrEtats.get(getIndiceEtatCourant());
        // ArrayList<Integer> tableIndices = new ArrayList<int>();
        //ajouter type StringPointIndiceligneconditions
        
        //System.out.println("\n\n ETAT courant : " + this.getListeEtats().get(this.getIndiceEtatCourant()));
        
        
        for(int i = 0; i < lignesTable.size() ; i++ ){
            //for(int j = 0; j < lignesTable.get(i).getListeCondBoole().size();j++){
            // parcourir lignesTable.get(i).getListeCondBoole() et verifier les conditions
            //System.out.println("\n LIGNE numero : " + i + "\n");
            eventPoint = conditionsValides(listeEvents,lignesTable.get(i).getListeCondBoole());
            if(eventPoint != null) // ajouter la fonction conditionsValides
            {
                //System.out.println("&&& conditions valide retourne : " + eventPoint.getEventAction() + " au point : (" + eventPoint.getPosition().getAbscisse() + "," + eventPoint.getPosition().getOrdonnee() + ")");
                
                
                if (actionPointIndexList == null){
                    actionPointIndexList = new ArrayList<StringPointIndiceligneconditions>();
                }
                //System.out.println("----> L'etat courant : " + this.getListeEtats().get(indiceEtatCourant));
                //System.out.println("----> L'etat suivant : " + lignesTable.get(i).getEtatSuiv());
                //System.out.println("----> L'action : " + lignesTable.get(i).getAction());
                
                
                ////System.out.println("L'etat suivant est : " +lignesTable.get(i).getEtatSuiv());
                
                etatSuivant = etatEstPresent(getListeEtats(),lignesTable.get(i).getEtatSuiv());
                //System.out.println("son indice est : " +etatSuivant);

                
                //etatSuivant = 2;
                //System.out.println("****************** etatSuivant selectionne : " + etatSuivant + " soit : " + this.getListeEtats().get(etatSuivant) +  " ***************");
                
                // a ce niveau etat suivant est correcte !, etatEstPresent aussi OK
               // System.out.println("****************** action : " + lignesTable.get(i).getAction());
                // l'action est la bonne aussi OK
                actionPointIndex = new StringPointIndiceligneconditions(lignesTable.get(i).getAction(),new Point(eventPoint.getPosition().getAbscisse(),eventPoint.getPosition().getOrdonnee()),etatSuivant);
                //System.out.println("****************** action " + actionPointIndex.getEventAction() + " avec prochain etat : " + actionPointIndex.getIndiceProchainEtat());
                // a ce niveau etat suivant est correcte !, etatEstPresent aussi OK
                
                actionPointIndexList.add(actionPointIndex);
                
                
                
            }
        }
        // en dehors de la boucle
        if(actionPointIndexList != null){
            if(actionPointIndexList.size() == 1){
                setIndiceEtatCourant(actionPointIndexList.get(0).getIndiceProchainEtat()) ; // a revoir
                actionPoint = new StringPoint(actionPointIndexList.get(0).getEventAction(),actionPointIndexList.get(0).getPosition());
            }
            else{
                //System.out.println("Affichage de la liste : ");
                for(int m = 0; m < actionPointIndexList.size();m++){
                    /*
                     * Les elements de la liste n'ont pas les bonnes coordonnées, c'est le cas de balle
                     *
                     */
                    
                    //System.out.println("element action " + m + " : " + actionPointIndexList.get(m).getEventAction() + " aux point : (" + actionPointIndexList.get(m).getPosition().getAbscisse() + "," + actionPointIndexList.get(m).getPosition().getOrdonnee() + ") indice prochain etat : " + actionPointIndexList.get(m).getIndiceProchainEtat());
                }
                
                // ETAT suivant OK
                
                /*
                 *
                 * Recupere le StringPoint le plus interessant !
                 * actionPoint = ....
                 * public static StringPoint selectBetterAction(ArrayList<StringPoint> actionPointList)
                 * selectBetterAction(actionPointList)
                 */
                
                
                actionPointIndex = StringPointIndiceligneconditions.selectBetterAction(actionPointIndexList);
                
                //System.out.println("L'action selectionnee est : " + actionPointIndex);
                
               // System.out.println("selectBetterAction retourne le point : ( " + actionPointIndex.getPosition().getAbscisse() + "," + actionPointIndex.getPosition().getOrdonnee() + ")");
                // il faut trouver un moyen de connaitre l'indice du prochain etat, soit le etatSuiv de l'action choisie
                
                setIndiceEtatCourant(actionPointIndex.getIndiceProchainEtat()) ;
                actionPoint=new StringPoint(actionPointIndex.getEventAction(),actionPointIndex.getPosition());
            }
            
            
        }
        
       //System.out.println("L'action est : " + actionPointIndex);

        
        // PROBLEME ACTION SUIVANTE OK mais PROCHAIN ETAT PAS BON
       // System.out.print("\n\n ETAT suivant : " + this.getListeEtats().get(this.getIndiceEtatCourant()));
       // System.out.println(" et ACTION : " + actionPoint.getEventAction());
        return actionPoint; // ne renvoie plus juste un String mais un StringPoint
    }
    
    
    // ajout fonction conditionsValides
    /*
     * public boolean conditionsValides(ArrayList<String> listeEvents,ArrayList<CondBoole> ListeCondBoole){
     * boolean booleRetour = false;
     *
     * for(int i = 0; i < ListeCondBoole.size();i++){
     * if(estPresent(listeEvents,ListeCondBoole.get(i).getCond()) != -1){
     * // est présent, il faut tester par rapport au booleen dans listecondboole
     * {
     * if(ListeCondBoole.get(i).getBoole() == true){
     * booleRetour = true;
     * break; // pas besoin de parcourir le reste des evenements, il faut sortir !!
     * //sinon PB si deux elements identiques existent
     * }
     * else {
     * // déjà a false
     * }
     * }
     *
     * }
     * else
     * {
     * if(ListeCondBoole.get(i).getBoole() == false){
     * booleRetour = true;
     * }
     * else {
     * // déjà a false
     * }
     *
     * }
     *
     * }
     *
     *
     * return booleRetour;
     * }
     */
    
    // nouvelle version - nouvelle structure
    // renvoie la position de l'evenement si les conditions sont validées
    public StringPoint conditionsValides(ArrayList<StringPoint> listeEvents,ArrayList<CondBoole> ListeCondBoole){
        // Point point = null;
        //Point pointReturn = null;
        StringPoint eventPoint = null;
        ArrayList<StringPoint> eventPointList = null;
        // int position;
        //int compteur = 0;
        ///StringPoint eventCourant = null;
        
        for(int i = 0; i < ListeCondBoole.size();i++){
            
            
            eventPoint = eventEstPresent(listeEvents,ListeCondBoole.get(i).getCond());
            
            if(eventPoint != null){
                //System.out.println("eventEstPresent renvoie : " + eventPoint.getEventAction() + " au point : (" + eventPoint.getPosition().getAbscisse() + "," + eventPoint.getPosition().getOrdonnee() + ")");
                // est présent, il faut tester par rapport au booleen dans listecondboole
                {
                if(ListeCondBoole.get(i).getBoole() == true){
                    if(eventPointList == null)
                    {
                        eventPointList =new ArrayList<StringPoint>();
                    }
                    //if (compteur == 0){
                    
                    eventPoint = new StringPoint(ListeCondBoole.get(i).getCond(),new Point(eventPoint.getPosition().getAbscisse(),eventPoint.getPosition().getOrdonnee()));
                    eventPointList.add(eventPoint);
                    //System.out.println("on ajout l'event : " + eventPointList.get(0).getEventAction());
                    // on récupère le point
                    // }
                    // else{
                    
                    // }
                    
                    // on ne récupère pas le point, on a déja le premier de la liste
                    
                    
                    // eventCourant = new StringPoint(ListeCondBoole.get(i).getCond(),listeEvents.get(i).getPosition());
                    //sinon PB si deux elements identiques existent
                    //System.out.println("Dans conditions valide IF 1");
                }
                else {
                    eventPointList = null;
                    //System.out.println("Dans conditions valide IF 2");
                    //break;
                }
            }
                
            }
            else
            {
                if(ListeCondBoole.get(i).getBoole() == false){
                    if(eventPointList == null)
                    {
                        eventPointList = new ArrayList<StringPoint>();
                    }
                   //System.out.println("eventEstPresent renvoie : valconditionfalseverifiee");
                    eventPoint = new StringPoint("valconditionfalseverifiee",new Point(0.0,0.0));
                    eventPointList.add(eventPoint);
                    // System.out.println("**on ajout l'event : " + eventPointList.get(0).getEventAction());
                    /*
                     *
                     * Renvoie un mur meme s'il n'y en a pas !!!!
                     *
                     */
                    
                    
                    // compteur ++;
                    // eventCourant = new StringPoint(ListeCondBoole.get(i).getCond(),listeEvents.get(i).getPosition());
                    //System.out.println("Dans conditions valide IF 3");
                }
                else {
                    eventPointList = null;
                    //System.out.println("Dans conditions valide IF 4");
                    //break;
                    
                }
                
            }
            
        }
        
        if (eventPointList != null){
            
            /*  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
             *
             * if faut recuperer le eventPoint le plus important et le renvoyer
             *  eventPoint =  public static StringPoint selectBetterEvent(ArrayList<StringPoint> eventPointList)
             *  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
             */
            
            //System.out.println("## Affichage de la liste des events dans conditionsvalides");
            
            /*
            for(int h = 0; h < eventPointList.size();h++){
                System.out.println("event n" + h + eventPointList.get(h).getEventAction() + "au point : (" + eventPointList.get(h).getPosition().getAbscisse() + "," + eventPointList.get(h).getPosition().getOrdonnee());
            }
            */
            
            eventPoint = StringPoint.selectBetterEvent(eventPointList);
            //System.out.println("ConditionsValides renvoie un point NULL, conditions pas valides");
        }
        // renvoie le StringPoint le plus important si les conditions sont validées
        return eventPoint;
    }
    
    
    
    // fonction actionEstPresent
    
    public int estPresent(ArrayList<StringPoint> listeEtats, String elem)
    {
        int position = -1;
        for(int i = 0; i < listeEtats.size();i++){
            // si l'etat est dans la liste : renvoie la position de l'etat  / evenement
            // s'il n'est pas dans la liste : renvoie -1
            if(listeEtats.get(i).getEventAction().compareTo(elem) == 0){
                // l'etat ou evenement est present
                position = i;
                break;
            }
            
        }
        return position;
    }
    
    
    public StringPoint eventEstPresent(ArrayList<StringPoint> listeEvents, String elem)
    {
        //System.out.println("entree est present");
        //int position = -1;
        Point point = null;
        StringPoint stringPoint = null;
        
        /*
        System.out.println("## ll des events apres tous les checks");
        for(int h = 0; h < listeEvents.size();h++){
            System.out.println("event num : " + h + ", nom : " + listeEvents.get(h).getEventAction() + " au point : (" + listeEvents.get(h).getPosition().getAbscisse() + "," + listeEvents.get(h).getPosition().getOrdonnee() + ")");
        }
        */
        
        for(int i = 0; i < listeEvents.size();i++){
            //System.out.println("La taille de la liste des events : " + listeEvents.size());
            //System.out.println("Dans la boucle liste etat a la taille est : " + listeEvents.size());
            // si l'etat est dans la liste : renvoie la position de l'etat  / evenement
            // s'il n'est pas dans la liste : renvoie -1
            //------------------- System.out.println("l'event est : " + listeEvents.get(i).getEventAction());
            if(listeEvents.get(i).getEventAction().compareTo(elem) == 0){
                // l'etat ou evenement est present
                //position = i;
                //System.out.println("l'event est present dans la liste : ");
                point = new Point(listeEvents.get(i).getPosition().getAbscisse(),listeEvents.get(i).getPosition().getOrdonnee());
                stringPoint = new StringPoint(listeEvents.get(i).getEventAction(),point);
                break;
            }
            
        }
        /*
        if(stringPoint != null){
            //System.out.println("## ll retourne fin eventeEstPresent : " + stringPoint.getEventAction());
            // System.out.println("Fin de la fonction est présent : ");
        }
        else
        {
            
            //System.out.println("## ll retourne fin eventeEstPresent : null");
        }
        */
        
        return stringPoint;
    }
    
    public int etatEstPresent(ArrayList<String> listeEtats, String elem)
    {
        int position = -1;
        for(int i = 0; i < listeEtats.size();i++){
            // si l'etat est dans la liste : renvoie la position de l'etat  / evenement
            // s'il n'est pas dans la liste : renvoie -1
            if(listeEtats.get(i).compareTo(elem) == 0){
                // l'etat ou evenement est present
                position = i;
                break;
            }
            
        }
        return position;
    }
    
    
    public static int etatEstPresentBis(ArrayList<String> listeEtats, String elem)
    {
        int position = -1;
        for(int i = 0; i < listeEtats.size();i++){
            // si l'etat est dans la liste : renvoie la position de l'etat  / evenement
            // s'il n'est pas dans la liste : renvoie -1
            if(listeEtats.get(i).compareTo(elem) == 0){
                // l'etat ou evenement est present
                position = i;
                break;
            }
            
        }
        return position;
    }
    
    
    // ajout d'une fonction affichage
    
    public void afficher(){
        System.out.println("******************************");
        System.out.println("*** Affichage de l'automate***");
        System.out.println("******************************");
        for(int i = 0;i < listePtrEtats.size();i++){
            System.out.println("\n Etat : " + listeEtats.get(i));
            System.out.println("etatSuiv|conditions|action");
            for(int j = 0; j < listePtrEtats.get(i).size();j++){
                System.out.print(listePtrEtats.get(i).get(j).getEtatSuiv() + " ");
                for(int k = 0;k < listePtrEtats.get(i).get(j).getListeCondBoole().size();k++){
                    System.out.print(listePtrEtats.get(i).get(j).getListeCondBoole().get(k).getCond() + "/" + listePtrEtats.get(i).get(j).getListeCondBoole().get(k).getBoole() + " ");
                }
                System.out.println(" " + listePtrEtats.get(i).get(j).getAction());
            }
            
            
        }
        
        
    }
    
    
    
    // getters et setters
    
    public int getIndiceEtatCourant() {
        return indiceEtatCourant;
    }
    
    public void setIndiceEtatCourant(int indiceEtatCourant) {
        this.indiceEtatCourant = indiceEtatCourant;
    }
    
    public ArrayList<String> getListeEtats() {
        return listeEtats;
    }
    
    public void setListeEtats(ArrayList<String> listeEtats) {
        this.listeEtats = listeEtats;
    }
    
    public ArrayList<ArrayList<EtatsuivCondsAction>> getListePtrEtats() {
        return listePtrEtats;
    }
    
    public void setListePtrEtats(ArrayList<ArrayList<EtatsuivCondsAction>> listePtrEtats) {
        this.listePtrEtats = listePtrEtats;
    }
    
    
    public void RemplirUneLigneAutomate(ArrayList<CondBoole> transition, String etatInit, String etatSuiv, String action){
        
        // a remplir
        int position;
        
        // On regarde si l'etat existe dejà dans la liste des etats
        position = etatEstPresent(this.getListeEtats(),etatInit);
        
        if(position == -1){
            this.getListeEtats().add(etatInit);
            position = this.getListeEtats().indexOf(etatInit);
            this.getListePtrEtats().add(new ArrayList<EtatsuivCondsAction>());
        }
        
        this.getListePtrEtats().get(position).add(new EtatsuivCondsAction(etatSuiv,transition,action));
        //this.getListePtrEtats().get(position).get(position)
        
        
    } // doit faire un new dedans
    
    
}
